﻿using Haidou.Wpf.Domian.Enums;
using Haidou.Wpf.Domian.Exceptions;
using Haidou.Wpf.Domian.Models;
using Haidou.Wpf.Util.Extensions;
using KGySoft.CoreLibraries;
using KGySoft.Reflection;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml;
using System.Xml.Linq;
using Key = System.Windows.Input.Key;
using Orientation = System.Windows.Controls.Orientation;
using XamlWriter = System.Windows.Markup.XamlWriter;
namespace Haidou.Wpf.Util.Settings
{
	public class UserSettings : INotifyPropertyChanged
	{
		#region Variables变量

		public event PropertyChangedEventHandler PropertyChanged;

		public static readonly object Lock = new();

		public static UserSettings All { get; } = new();

		public Version? Version => Assembly.GetEntryAssembly()?.GetName().Version;

		public string VersionText => Version?.ToStringShort() ?? "0.0";

		protected static ResourceDictionary _local;
		protected static ResourceDictionary _appData;
		private static readonly ResourceDictionary Default;

		#endregion

		static UserSettings()
		{
			if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
			{
				return;
			}

			//LoadRSAEncryptSettings();


			//Tries to load both settings files (from the local or AppData folder).尝试加载两个设置文件(从本地或AppData文件夹)。
			LoadSettings();



			//Reads the default settings (it's loaded by default).读取默认设置(默认情况下加载)。
			Default = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.EndsWith("/Settings.xaml"));
		}


		private static void LoadRSAEncryptSettings()
		{
			//Paths. 路径

			string appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop") + "\\Config\\Settings.xaml";

			//仅在未定义本地设置的情况下创建空的AppData设置文件。
			if (!File.Exists(appData))
			{
				string? directory = Path.GetDirectoryName(appData);

				if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
				{
					Directory.CreateDirectory(directory);
				}

				//只创建一个没有任何属性的资源字典。
				File.WriteAllText(appData, "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"></ResourceDictionary>");
			}

			//加载AppData设置。
			if (File.Exists(appData))
			{
				_appData = Load(appData) ?? new ResourceDictionary();
				Application.Current.Resources.MergedDictionaries.Add(_appData);
			}



		}



		private static void LoadSettings()
		{
			//Paths. 路径
			string local = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.xaml");
			string appData = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop"), "Settings.xaml");

			//仅在未定义本地设置的情况下创建空的AppData设置文件。
			if (!File.Exists(local) && !File.Exists(appData))
			{
				string? directory = Path.GetDirectoryName(appData);

				if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
				{
					Directory.CreateDirectory(directory);
				}

				//只创建一个没有任何属性的资源字典。
				File.WriteAllText(appData, "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"></ResourceDictionary>");
			}

			//加载AppData设置。
			if (File.Exists(appData))
			{
				_appData = Load(appData) ?? new ResourceDictionary();
				Application.Current.Resources.MergedDictionaries.Add(_appData);
			}

			//加载本地设置。
			if (File.Exists(local))
			{
				_local = Load(local);

				if (_local != null)
				{
					Application.Current.Resources.MergedDictionaries.Add(_local);
				}
			}
		}

		private static ResourceDictionary Load(string path)
		{
			try
			{
				#region Load settings from disk从磁盘加载设置

				XDocument doc = XDocument.Parse(File.ReadAllText(path));
				System.Collections.Generic.List<Property>? properties = doc.Root?.Elements().Select(GetProperty).ToList();

				#endregion

				#region Migrate 迁移。移动

				//string version = properties?.FirstOrDefault(f => f.Key == "Version")?.Value ?? "0.0";

				//Migration.Migrate(properties, version);

				#endregion

				#region Parse settings解析设置

				//由于设置已迁移，请添加当前版本。
				ResourceDictionary resource = new()
				{
				{ "Version", All.VersionText }
				};

				foreach (Property? property in properties)
				{
					object value = ParseProperty(property);

					if (value != null && !resource.Contains(property.Key))
					{
						resource.Add(property.Key, value);
					}
				}

				#endregion

				return resource;
			}
			catch (Exception e)
			{
				LogWriter.Log(e, "It was not possible to load and migrate the settings.||无法加载和迁移设置");//无法加载和迁移设置。
				return null;
			}
		}

		/// <summary>
		/// 获取属性
		/// </summary>
		/// <param name="node"></param>
		/// <returns></returns>
		public static Property GetProperty(XElement node)
		{
			System.Collections.Generic.List<Property> attributes = node.Attributes()
				.Where(a => a.Name.LocalName != "Key" && !(a.Name.Namespace == XNamespace.Xml && a.Name.LocalName == "space"))
				.Select(s => new Property { Key = s.Name.LocalName, Value = s.Value })
				.ToList();

			Property prop = new()
			{
				NameSpace = node.Name.NamespaceName,
				Type = node.Name.LocalName,
				Key = node.Attributes().FirstOrDefault(a => a.Name.LocalName == "Key")?.Value,
				Attributes = attributes,
				Value = node.Value
			};

			if (node.Name.LocalName.StartsWith("Null"))
			{
				return null;
			}

			if (!node.HasElements)
			{
				return prop;
			}

			//展平被分成另一个标签的属性。
			if (attributes.Count == 0 && (prop.Type ?? "").Contains("."))
			{
				Property? inner = node.Elements().Select(GetProperty).FirstOrDefault();

				if (inner != null)
				{
					prop.Key = prop.Type.Split('.').LastOrDefault();
					prop.Type = inner.Type;
					prop.NameSpace = inner.NameSpace;
					prop.Children = inner.Children;
					prop.Attributes = inner.Attributes;
					return prop;
				}
			}

			foreach (XElement element in node.Elements())
			{
				Property innerElement = GetProperty(element);

				if (innerElement != null)
				{
					// 向子级添加集合元素，向属性添加属性
					if (innerElement.Key == null)
					{
						prop.Children.Add(innerElement);
					}
					else
					{
						prop.Attributes.Add(innerElement);
					}
				}
			}

			return prop;
		}

		/// <summary>
		/// 解析属性
		/// </summary>
		/// <param name="property"></param>
		/// <returns></returns>
		private static object ParseProperty(Property property)
		{
			try
			{
				Type type = ParseType(property);

				// 基元/简单类型、枚举或具有TypeConverter的类型
				if (property.Attributes.Count == 0)
				{
					return ParseValue(property.Value, type);
				}

				//具有属性/项目的复杂对象
				object? instance = Activator.CreateInstance(type);

				// 恢复属性
				foreach (Property prop in property.Attributes)
				{
					PropertyInfo info = type.GetProperty(prop.Key) ?? throw new ArgumentException($"Property not found: {type.Name}.{prop.Key}", nameof(property));
					PropertyAccessor.GetAccessor(info).Set(instance, prop.Type != null ? ParseProperty(prop) : ParseValue(prop.Value, info.PropertyType));
				}

				// 恢复集合项(事实上，由于WPF序列化，list总是一个ArrayList，但是理论上我们也支持其他的)
				if (instance is IList list)
				{
					foreach (Property child in property.Children)
					{
						list.Add(ParseProperty(child));
					}
				}

				return instance;
			}
			catch (Exception e)
			{
				LogWriter.Log(e, "Impossible to parse property", property);//无法解析属性
				return null;
			}
		}

		/// <summary>
		/// 解析类型
		/// </summary>
		/// <param name="property"></param>
		/// <returns></returns>
		private static Type ParseType(Property property)
		{
			if (property.NameSpace is "clr-namespace:System;assembly=System.Private.CoreLib" or "clr-namespace:System;assembly=mscorlib")
			{
				return Type.GetType("System." + property.Type, true);
			}

			// 用反射器代替铅字。因为没有程序集类型。GetType仅适用于mscorlib/System。Private.CoreLib类型
			if (property.NameSpace.StartsWith("http", StringComparison.Ordinal))
			{
				return Reflector.ResolveType("System.Windows." + property.Type, ResolveTypeOptions.None)
					?? Reflector.ResolveType("System.Windows.Media." + property.Type, ResolveTypeOptions.None)
					?? Reflector.ResolveType("System.Windows.Ink." + property.Type, ResolveTypeOptions.None)
					?? Reflector.ResolveType("System.Windows.Input." + property.Type, ResolveTypeOptions.None)
					?? Reflector.ResolveType("System.Windows.Controls." + property.Type, ResolveTypeOptions.ThrowError);
			}

			int namespaceIndex = property.NameSpace.IndexOf("clr-namespace:", StringComparison.Ordinal);
			string space = property.NameSpace.Substring(namespaceIndex + 14);
			int assemblyIndex = space.IndexOf(";assembly=", StringComparison.Ordinal);

			if (assemblyIndex == -1)
			{
				return Reflector.ResolveType(space + "." + property.Type, ResolveTypeOptions.ThrowError);
			}

			// 警报:ResolveTypeOptions。TryToLoadAssemblies有安全风险，但这是与类型兼容的行为。GetType(assemblyQualifiedName)，它也可以加载任何程序集。
			string assembly = space.Substring(assemblyIndex + 10);
			space = space.Substring(0, space.Length - assembly.Length - 10);
			return Reflector.ResolveType(space + "." + property.Type + ", " + assembly, ResolveTypeOptions.AllowPartialAssemblyMatch | ResolveTypeOptions.TryToLoadAssemblies | ResolveTypeOptions.ThrowError);
		}

		/// <summary>
		/// 解析值
		/// </summary>
		/// <param name="value"></param>
		/// <param name="type"></param>
		/// <returns></returns>
		private static object ParseValue(string value, Type type)
		{
			try
			{


				if (value is null or "{x:Null}")
				{
					return null;
				}

				if (type == typeof(string))
				{
					return value.StartsWith("{}", StringComparison.Ordinal) ? value[2..] : value;
				}

				// 这适用于基元类型、枚举和具有类型转换器的类型
				if (value.TryParse(type, CultureInfo.InvariantCulture, out object? result))
				{
					return result;
				}

				// 对于应该由TypeConverters而不是从其ToString值(如ModifierKeys)分析的枚举，[Try]分析失败
				//我们可以只使用Convert even来代替上面的解析，但是只使用它作为后备会更快
				return value.Convert(type, CultureInfo.InvariantCulture);
			}
			catch (Exception ex)
			{
				Debug.WriteLine(ex.Message);
				throw;
			}
		}

		public static void Save(bool canForce = false, bool saveToAppData = false)
		{
			//仅在创建了非默认值时写入。不应该写默认字典。
			if (_local == null && _appData == null)
			{
				return;
			}

			try
			{
				//文件名(本地或AppData)。
				string folder = !saveToAppData && _local != null ? AppDomain.CurrentDomain.BaseDirectory : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop");
				string filename = Path.Combine(folder, "Settings.xaml");

				//创建文件夹。
				if (!string.IsNullOrWhiteSpace(folder) && !Directory.Exists(folder))
				{
					Directory.CreateDirectory(folder);
				}

				string? backup = File.Exists(filename) ? File.ReadAllText(filename) : null;

				XmlWriterSettings settings = new()
				{
					Indent = true,
					IndentChars = "\t",
					OmitXmlDeclaration = true,
					CheckCharacters = true,
					CloseOutput = true,
					ConformanceLevel = ConformanceLevel.Fragment,
					Encoding = Encoding.UTF8
				};

				ResourceDictionary dic = RemoveInvalidEntries(_local ?? _appData);

				if (dic == null)
				{
					return;
				}

				//序列化并保存到磁盘。
				using (FileStream fileStream = new(filename, FileMode.Create, FileAccess.Write, FileShare.None))
				using (XmlWriter writer = XmlWriter.Create(fileStream, settings))
				{
					XamlWriter.Save(dic, writer);
				}

				CheckIfSavedCorrectly(filename, backup, true);//检查是否正确保存
			}
			catch (UnauthorizedAccessException u)
			{
				//尝试先保存到AppData，然后再努力。
				if (!saveToAppData)
				{
					Save(canForce, true);
				}
				else if (canForce)
				{
					LogWriter.Log(u, "Unauthorized to save the settings.未授权保存设置");//未授权保存设置
					throw new SettingsPersistenceException(_local ?? _appData, _local != null);
				}
			}
			catch (Exception e) when (e is not SettingsPersistenceException)
			{
				LogWriter.Log(e, "Impossible to save the settings.无法保存设置");//无法保存设置
			}
		}

		public static void SaveRSAEncrypt(bool canForce = false, bool saveToAppData = false)
		{
			//仅在创建了非默认值时写入。不应该写默认字典。
			if (_local == null && _appData == null)
			{
				return;
			}

			try
			{
				string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop") + "\\Config";

				//文件名(本地或AppData)。
				string filename = Path.Combine(folder, "Settings.xaml");

				//创建文件夹。
				if (!string.IsNullOrWhiteSpace(folder) && !Directory.Exists(folder))
				{
					Directory.CreateDirectory(folder);
				}

				string? backup = File.Exists(filename) ? File.ReadAllText(filename) : null;

				XmlWriterSettings settings = new()
				{
					Indent = true,
					IndentChars = "\t",
					OmitXmlDeclaration = true,
					CheckCharacters = true,
					CloseOutput = true,
					ConformanceLevel = ConformanceLevel.Fragment,
					Encoding = Encoding.UTF8
				};

				ResourceDictionary dic = RemoveInvalidEntries(_local ?? _appData);

				if (dic == null)
				{
					return;
				}

				//序列化并保存到磁盘。
				using (FileStream fileStream = new(filename, FileMode.Create, FileAccess.Write, FileShare.None))
				using (XmlWriter writer = XmlWriter.Create(fileStream, settings))
				{
					XamlWriter.Save(dic, writer);
				}

				CheckIfSavedCorrectly(filename, backup, true);//检查是否正确保存
			}
			catch (UnauthorizedAccessException u)
			{
				//尝试先保存到AppData，然后再努力。
				if (!saveToAppData)
				{
					Save(canForce, true);
				}
				else if (canForce)
				{
					LogWriter.Log(u, "Unauthorized to save the settings.未授权保存设置");//未授权保存设置
					throw new SettingsPersistenceException(_local ?? _appData, _local != null);
				}
			}
			catch (Exception e) when (e is not SettingsPersistenceException)
			{
				LogWriter.Log(e, "Impossible to save the settings.无法保存设置");//无法保存设置
			}
		}



		/// <summary>
		/// 从另一个实例保存
		/// </summary>
		/// <param name="serialized"></param>
		/// <param name="isLocal"></param>
		public void SaveFromAnotherInstance(string serialized, bool isLocal)
		{
			try
			{
				//Filename (Local or AppData).文件名（本地或AppData）。
				string folder = _local != null ? AppDomain.CurrentDomain.BaseDirectory : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop");
				string filename = Path.Combine(folder, "Settings.xaml");
				string backup = filename + ".bak";

				//Create folder.创建文件夹。
				if (!string.IsNullOrWhiteSpace(folder) && !Directory.Exists(folder))
				{
					Directory.CreateDirectory(folder);
				}

				//Create the backup, in case the save operation fails.创建备份，以防保存操作失败。
				if (File.Exists(filename))
				{
					File.Copy(filename, backup, true);
				}

				//Serialize and save to disk.序列化并保存到磁盘。
				using (FileStream fileStream = new(filename, FileMode.Create, FileAccess.Write, FileShare.None))
				using (StreamWriter writer = new(fileStream, Encoding.UTF8))
				{
					writer.Write(serialized);
				}

				CheckIfSavedCorrectly(filename, backup);

				File.Delete(backup);
			}
			catch (Exception e)
			{
				LogWriter.Log(e, "Impossible to retry saving the settings.无法重试保存设置");
			}
		}

		/// <summary>
		/// 检查是否正确保存
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="backup"></param>
		/// <param name="throwException"></param>
		private static void CheckIfSavedCorrectly(string filename, string backup, bool throwException = false)
		{
			try
			{
				string content = File.ReadAllText(filename);

				if (content.All(x => x == '\0'))
				{
					LogWriter.Log("Settings disk persistence failed.设置磁盘持久性失败", content);
					File.WriteAllText(filename, backup);

					if (throwException)
					{
						throw new UnauthorizedAccessException("The file had garbage inside it.文件里有垃圾");
					}
				}
			}
			catch (Exception e)
			{
				LogWriter.Log(e, "Impossible to check if the settings file was saved correctly or impossible to restore backup.无法检查设置文件是否保存正确或无法恢复备份");
			}
		}

		/// <summary>
		/// 删除无效条目
		/// </summary>
		/// <param name="dictionary"></param>
		/// <returns></returns>
		private static ResourceDictionary RemoveInvalidEntries(ResourceDictionary dictionary)
		{
			if (dictionary == null)
			{
				return null;
			}

			System.Collections.Generic.List<DictionaryEntry> toRemove = dictionary.Cast<DictionaryEntry>().Where(entry => entry.Value == null).ToList();

			foreach (DictionaryEntry entry in toRemove)
			{
				LogWriter.Log("Setting removed.设置已移除: " + entry.Key);
				dictionary.Remove(entry.Key);
			}

			for (int i = 0; i < dictionary.Count; i++)
			{
				if (dictionary[i] is DictionaryEntry { Value: ArrayList list } entry)
				{
					entry.Value = list.OfType<object>().Where(w => w != null);
				}
			}

			return dictionary;
		}


		public static void CreateLocalSettings()
		{
			string local = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.xaml");

			if (!File.Exists(local))
			{
				File.WriteAllText(local, "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"></ResourceDictionary>");
			}

			_local = new ResourceDictionary();
		}

		public static void RemoveLocalSettings()
		{
			string local = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.xaml");

			if (File.Exists(local))
			{
				File.Delete(local);
			}

			_local = null; //TODO: Should I remove from the merged dictionaries?  我应该从合并的词典中删除吗？
		}


		/// <summary>
		/// 删除配置文件
		/// </summary>

		public static void RemoveAppDataSettings()
		{
			string appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop", "Settings.xaml");

			if (File.Exists(appData))
			{
				File.Delete(appData);
			}

			_appData = null; //TODO: Should I remove from the merged dictionaries?我应该从合并的词典中删除吗？
		}

		/// <summary>
		/// 删除配置文件
		/// </summary>

		public static void RemoveAppDataSettingsRSAEncrypt()
		{

			string appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Haidou.Desktop") + "\\Config\\Settings.xaml";

			if (File.Exists(appData))
			{
				File.Delete(appData);
			}

			_appData = null; //TODO: Should I remove from the merged dictionaries?我应该从合并的词典中删除吗？
		}



		private static object GetValue([CallerMemberName] string key = "", object defaultValue = null)
		{
			if (Default == null)
			{
				return defaultValue;
			}

			if (Application.Current == null || Application.Current.Resources.Count == 0)
			{
				return Default[key];
			}

			return Application.Current.Resources.Contains(key) ? Application.Current.Resources[key] : Default[key] ?? defaultValue;
		}

		private static void SetValue(object value, [CallerMemberName] string key = "")
		{
			lock (Lock)
			{
				//Updates or inserts the value to the Local resource.在本地资源中更新或插入值。
				if (_local != null)
				{
					if (_local.Contains(key))
					{
						_local[key] = value;

						//If the value is being set to null, remove it.如果该值被设置为null，请将其删除。
						if (value == null && (!Default.Contains(key) || Default[key] == null))
						{
							_local.Remove(key);
						}
					}
					else
					{
						if (value != null)
						{
							_local.Add(key, value);
						}
					}
				}

				//Updates or inserts the value to the AppData resource.向AppData资源更新或插入值。
				if (_appData != null)
				{
					if (_appData.Contains(key))
					{
						_appData[key] = value;

						//If the value is being set to null, remove it.如果该值被设置为null，请将其删除。
						if (value == null && (!Default.Contains(key) || Default[key] == null))
						{
							_appData.Remove(key);
						}
					}
					else
					{
						if (value != null)
						{
							_appData.Add(key, value);
						}
					}
				}

				//Updates/Adds the current value of the resource.更新/添加资源的当前值。
				if (Application.Current.Resources.Contains(key))
				{
					Application.Current.Resources[key] = value;
				}
				else
				{
					Application.Current.Resources.Add(key, value);
				}

				All.OnPropertyChanged(key);
			}
		}

		private void OnPropertyChanged(string? propertyName = null)
		{
			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
		}


		#region Properties 属性

		#region Startup

		public double StartupTop
		{
			get => (double)GetValue();
			set => SetValue(value);
		}

		public double StartupLeft
		{
			get => (double)GetValue();
			set => SetValue(value);
		}

		public double StartupHeight
		{
			get => (double)GetValue();
			set => SetValue(value);
		}

		public double StartupWidth
		{
			get => (double)GetValue();
			set => SetValue(value);
		}

		public WindowState StartupWindowState
		{
			get => (WindowState)GetValue();
			set => SetValue(value);
		}




		/// <summary>
		/// 当前进程id
		/// </summary>
		public int CurrentProcessId
		{
			get => (int)GetValue();
			set => SetValue(value);
		}



		#endregion

		#region Mouser
	

		#endregion


		



		

		#region Video source

		public int VideoImporter
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		#endregion

		#region Feedback

		public string LatestFeedbackEmail
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		#endregion


		#region Options • Application

		public bool SingleInstance
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool StartMinimized
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// The homepage of the app:
		/// 0 - Startup window.
		/// 1 - Recorder window.
		/// 2 - Webcam window.
		/// 3 - Board window.
		/// 4 - Editor window.
		/// </summary>
		public int StartUp
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public bool NotifyWhileClosingApp
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool DisableHardwareAcceleration
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool CheckForTranslationUpdates
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool CheckForUpdates
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool PortableUpdate
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool ForceUpdateAsAdmin
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool InstallUpdates
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool PromptToInstall
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool ShowNotificationIcon
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool KeepOpen
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 0: Do nothing.
		/// 1: Open a new window.
		/// 2: Toggle Minimize/Maximize all windows.
		/// 3: Minimize all windows.
		/// 4: Maximize all windows.
		/// </summary>
		public int LeftClickAction
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 0: None.
		/// 1: Startup
		/// 2: Screen recorder
		/// 3: Webcam recorder
		/// 4: Board recorder
		/// 5: Editor
		/// </summary>
		public int LeftOpenWindow
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public int DoubleLeftClickAction
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public int DoubleLeftOpenWindow
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public int MiddleClickAction
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public int MiddleOpenWindow
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		//变通办法

		public bool WorkaroundQuota
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 开机启动
		/// </summary>
		public bool? Startup
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}
		/// <summary>
		/// 单例运行
		/// </summary>
		public bool? Singleinstancerun
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 启动最小化到系统托盘
		/// </summary>
		public bool? StartMinimizetoSystemTray
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 启动使用的应用  打开的窗口是那个
		/// </summary>
		public string Launchingapplicationsforuse
		{
			get => (string)GetValue();
			set => SetValue(value);
		}



		/// <summary>
		/// 关闭应用程序之前询问我
		/// </summary>
		public bool? Askmebeforeclosingtheapplication
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}
		/// <summary>
		/// 关闭硬件加速
		/// </summary>
		public bool? Turnoffhardwareacceleration
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}
		/// <summary>
		/// 检查翻译更新
		/// </summary>
		public bool? Checkfortranslationupdates
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 自动升级
		/// </summary>
		public bool? Checkforupdates_automaticupgrade
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 强制下载便携版本
		/// </summary>
		public bool? Forcedownloadofportableversion
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 强制更新时提示权限
		/// </summary>
		public bool? Promptforpermissionswhenforcingupdates
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 是否自动输入
		/// </summary>
		public bool? Automaticinputornot
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}
		/// <summary>
		/// 强制下载安装包版本
		/// </summary>
		public bool? ForceDownloadOfTheInstallationPackageVersion
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		/// 打开语音唤醒检查
		/// </summary>
		public bool? TurnonVoiceWakeUpCheck
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}

		public string DPI
		{
			get => (string)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		/// 截屏翻译 开始语音
		/// </summary>
		public string JP_language
		{
			get => (string)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		/// 截屏翻译 开始语音
		/// </summary>
		public string JP_language_OUT
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		/// <summary>
		///  开始语音
		/// </summary>
		public string HC_language
		{
			get => (string)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		///  开始语音
		/// </summary>
		public string HC_language_OUT
		{
			get => (string)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		/// 是否在后处理中添加标点，默认是false。
		/// </summary>
		public bool? IntelligentPunctuationMark
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		/// 我的母语
		/// </summary>
		public string MyMotherTongue
		{
			get => (string)GetValue();
			set => SetValue(value);
		}


		/// <summary>
		/// 是新版本界面吗
		/// </summary>
		public bool? Isitanewversionoftheinterface
		{
			get => (bool?)GetValue();
			set => SetValue(value);
		}






		#endregion

	

		#region Options • Automated Tasks

		public ArrayList AutomatedTasksList
		{
			get => (ArrayList)GetValue();
			set => SetValue(value);
		}

		#endregion

		#region Options • Shortcuts



		public Key ExpandPhoneticTypingShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandPhoneticTypingModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key ExpandAIQuestionandanswerShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAIQuestionandanswerModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key ExpandAISelectShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAISelectModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key ExpandTranslationShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandTranslationModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}


		public Key ExpandIntelligentwritingShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandIntelligentwritingModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}






		public Key ExpandDocumentSummaryShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandDocumentSummaryModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}


		public Key ExpandMeetingMinutesShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandMeetingMinutesModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}

		public Key ExpandOneKeyPPTShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandOneKeyPPTModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}

		public Key ExpandAIFormShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAIFormModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}


		public Key ExpandOfficeTemplateShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandOfficeTemplateModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}


		public Key ExpandAIpaintingShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAIpaintingModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}


		public Key ExpandAIEliminationShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAIEliminationModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}


		public Key ExpandAIMattingShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandAIMattingModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}




		public Key ExpandScreenshotShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandScreenshotModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}


		public Key ExpandMkeyShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExpandMkeyModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);


		}



		public Key ScreenshotFullShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ScreenshotFullModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}


		public Key ScreenshotShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ScreenshotModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key CustomKeySettingsShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys CustomKeySettingsModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key BoardRecorderShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public Key OpenSettings
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}


		public Key OpenAIassistant
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}


		public ModifierKeys OpenAIassistantModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}



		public ModifierKeys BoardRecorderModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public ModifierKeys OpenSettingsModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}


		public Key EditorShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys EditorModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key OptionsShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys OptionsModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key ExitShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys ExitModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}


		public Key StartPauseShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys StartPauseModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key StopShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys StopModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key DiscardShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys DiscardModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public Key FollowShortcut
		{
			get => (Key)GetValue(defaultValue: Key.None);
			set => SetValue(value);
		}

		public ModifierKeys FollowModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		public ModifierKeys DisableFollowModifiers
		{
			get => (ModifierKeys)GetValue(defaultValue: ModifierKeys.None);
			set => SetValue(value);
		}

		#endregion

		#region Options • Language

		public string LanguageCode
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		#endregion

		#region Options • Storage
		/// <summary>
		/// TemporaryFolder
		/// </summary>
		public string TemporaryFolder
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		public string LogsFolder
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		public string TemporaryFolderResolved
		{
			get
			{
				if (string.IsNullOrWhiteSpace(TemporaryFolder))
				{
					TemporaryFolder = "%temp%";
				}

				return Environment.ExpandEnvironmentVariables(TemporaryFolder);//替换嵌入在指定字符串中的每个环境变量的名称
																			   //使用变量值的等效字符串，然后返回结果
																			   //字符串。
			}
		}

		public bool DeleteCacheWhenClosing
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool AskDeleteCacheWhenClosing
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public bool AutomaticCleanUp
		{
			get => (bool)GetValue();
			set => SetValue(value);
		}

		public int AutomaticCleanUpDays
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		#endregion

		#region Options • Cloud

		//Proxy.
		public ProxyTypes ProxyMode
		{
			get => (ProxyTypes)GetValue(defaultValue: ProxyTypes.Disabled);
			set => SetValue(value);
		}

		public string ProxyHost
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		public int ProxyPort
		{
			get => (int)GetValue();
			set => SetValue(value);
		}

		public string ProxyUsername
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		public string ProxyPassword
		{
			get => (string)GetValue();
			set => SetValue(value);
		}

		//Presets.
		public ArrayList UploadPresets
		{
			get => (ArrayList)GetValue();
			set => SetValue(value);
		}

		#endregion


		#endregion


	}
}
